7.3: Penerima Siaran
Materi:
Maksud eksplisit digunakan untuk memulai aktivitas tertentu yang benar-benar memenuhi syarat, serta untuk meneruskan informasi di antara aktivitas di aplikasi Anda. Maksud implisit digunakan untuk memulai aktivitas berdasarkan komponen terdaftar yang diketahui sistem, misalnya fungsionalitas umum.
Dalam pelajaran ini Anda akan mempelajari tentang maksud siaran, yang tidak memulai aktivitas namun dikirimkan ke penerima siaran.
Maksud siaran
Maksud yang telah Anda lihat sejauh ini selalu menghasilkan aktivitas yang akan diluncurkan, baik aktivitas tertentu dari aplikasi Anda maupun aktivitas dari aplikasi lain yang bisa memenuhi aksi yang diminta. Namun kadang-kadang maksud tidak memiliki penerima tertentu, dan kadang-kadang Anda tidak ingin aktivitas diluncurkan sebagai respons terhadap maksud. Misalnya, bila aplikasi Anda menerima maksud sistem yang menunjukkan bahwa keadaan jaringan di perangkat sudah berubah, Anda mungkin tidak ingin meluncurkan aktivitas, melainkan mungkin ingin menonaktifkan beberapa fungsionalitas aplikasi.
Karena alasan ini, ada tipe maksud ketiga yang bisa dikirimkan ke aplikasi yang tertarik: maksud siaran. Meskipun maksud siaran didefinisikan dengan cara yang sama seperti maksud implisit, setiap tipe maksud memiliki karakteristik pembeda yang penting:
- Maksud siaran dikirim menggunakan
sendBroadcast()
atau metode terkait, sementara tipe maksud lainnya menggunakanstartActivity()
untuk memulai aktivitas. Bila menyiarkan maksud, Anda tidak akan pernah menemukan atau memulai aktivitas. Demikian juga, tidak ada cara bagi penerima siaran untuk melihat atau menangkap maksud yang digunakan bersamastartActivity()
. - Maksud siaran adalah operasi latar belakang yang biasanya tidak diketahui pengguna. Memulai aktivitas bersama maksud, di sisi lain, adalah operasi latar depan yang memodifikasi apa yang sedang berinteraksi dengan pengguna.
Ada dua tipe maksud siaran, yang dikirimkan oleh sistem (maksud siaran sistem), dan yang dikirimkan oleh aplikasi Anda (maksud siaran khusus).
Maksud siaran sistem
Sistem mengirimkan maksud siaran sistem bila ada kejadian sistem yang mungkin menarik aplikasi. Misalnya:
- Bila perangkat sedang booting, sistem akan mengirim sebuah maksud siaran sistem
ACTION_BOOT_COMPLETED
. Maksud ini berisi nilai konstanta"android.intent.action.BOOT_COMPLETED"
. - Bila perangkat terhubung ke daya eksternal, sistem akan mengirim
ACTION_POWER_CONNECTED
, yang berisi nilai konstanta"android.intent.action.ACTION_POWER_CONNECTED"
. Bila perangkat terlepas dari daya eksternal, sistem akan mengirimACTION_POWER_DISCONNECTED
. - Bila memori perangkat minim, sistem akan mengirim
ACTION_DEVICE_STORAGE_LOW
. Maksud ini berisi nilai konstanta"android.intent.action.DEVICE_STORAGE_LOW"
.
ACTION_DEVICE_STORAGE_LOW
merupakan siaran melekat, maksudnya adalah nilai siaran bertahan di cache. Jika Anda perlu mengetahui apakah penerima siaran memproses nilai yang ada di cache (melekat) atau nilai yang disiarkan pada saat ini, gunakan isInitialStickyBroadcast()
.
Untuk informasi selengkapnya tentang siaran sistem umum, kunjungi referensi Intent
.
Untuk menerima maksud siaran sistem, Anda perlu membuat penerima siaran.
Maksud siaran khusus
Maksud siaran khusus adalah maksud siaran yang dikirim aplikasi Anda. Gunakan maksud siaran khusus bila Anda ingin agar aplikasi mengambil suatu aksi tanpa meluncurkan aktivitas, misalnya bila Anda ingin membiarkan aplikasi lainnya mengetahui bahwa data telah diunduh ke perangkat dan tersedia untuk digunakan.
Untuk membuat maksud siaran khusus, buat aksi maksud khusus. Untuk mengirim siaran khusus ke aplikasi lainnya, teruskan maksud ke sendBroadcast()
, sendOrderedBroadcast()
, atau sendStickyBroadcast()
. (Untuk detail tentang metode ini, lihat dokumentasi referensi Context
.)
Misalnya, metode berikut membuat sebuah maksud dan menyiarkannya ke semua [penerima siaran] yang tertarik(#broadcast_receivers):
public void sendBroadcastIntent() {
Intent intent = new Intent();
intent.setAction("com.example.myproject.ACTION_SHOW_TOAST");
sendBroadcast(intent);
}
com.example.myproject
dalam contoh) untuk memastikan maksud tersebut tidak konflik dengan maksud yang disiarkan dari aplikasi lain atau dari sistem.
Penerima siaran
Maksud siaran tidak ditargetkan pada penerima tertentu. Sebagai gantinya, aplikasi yang tertarik mendaftarkan komponen untuk "mendengarkan" jenis maksud ini. Komponen pendengar ini disebut penerima siaran.
Gunakan penerima siaran untuk merespons pesan yang disiarkan dari aplikasi lain atau dari sistem. Untuk membuat penerima siaran:
- Definisikan sub kelas dari kelas
BroadcastReceiver
dan implementasikan metodeonReceive()
. Daftarkan penerima siaran secara dinamis di Java, atau secara statis di file manifes aplikasi Anda.
Sebagai bagian dari langkah ini, gunakan filter maksud untuk menetapkan jenis maksud siaran yang ingin Anda terima.
Langkah-langkah ini dijelaskan di bawah.
Definisikan subkelas BroadcastReceiver
Untuk membuat penerima siaran, definisikan subkelas dari kelas BroadcastReceiver
. Di subkelas inilah maksud dikirim (jika cocok dengan filter maksud yang Anda setel saat mendaftarkan subkelas, yang terjadi di langkah berikutnya).
Dalam definisi subkelas Anda:
- Implementasikan metode
onReceive()
yang diperlukan. - Sertakan logika apa pun yang diperlukan penerima siaran Anda.
Contoh: Buat penerima siaran
Dalam contoh ini, subkelas AlarmReceiver
dari BroadcastReceiver
menampilkan pesan Toast jika maksud siaran yang masuk memiliki aksi ACTION_SHOW_TOAST
:
private class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_SHOW_TOAST)) {
CharSequence text = "Broadcast Received!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
}
onReceive()
, karena setelah kode Anda kembali dari onReceive()
, sistem akan menganggap objek BroadcastReceiver
akan diselesaikan. Jika onReceive()
memulai operasi asinkron, sistem akan mematikan proses BroadcastReceiver
sebelum operasi asinkron memiliki kesempatan untuk diselesaikan.
Jika Anda memerlukan operasi yang berjalan lama yang tidak memerlukan UI, gunakan Service yang diluncurkan dari penerima siaran. Khususnya:
- Anda tidak bisa menampilkan dialog dari dalam
BroadcastReceiver
. Sebagai gantinya, gunakanNotificationManager
API. - Anda tidak bisa mengikat ke layanan dari dalam
BroadcastReceiver
. Sebagai gantinya, gunakanContext.startService()
untuk mengirim perintah ke layanan.
Mendaftarkan penerima siaran Anda dan menyetel filter maksud
Ada dua cara untuk mendaftarkan penerima siaran: secara statis di manifes, atau secara dinamis di aktivitas Anda.
Pendaftaran statis
Untuk mendaftarkan penerima siaran secara statis, tambahkan elemen <receiver>
ke file AndroidManifest.xml Anda. Dalam elemen <receiver>
:
- Gunakan jalur ke subkelas
BroadcastReceiver
sebagai atributandroid:name
. - Untuk mencegah aplikasi lain mengirim siaran ke penerima Anda, setel atribut
android:exported
opsional kefalse
. Ini adalah [panduan keamanan] penting(#security). - Untuk menetapkan tipe maksud yang akan didengarkan komponen, gunakan elemen
<intent-filter>
yang disarangkan.
Contoh: Pendaftaran statis dan filter maksud untuk maksud siaran khusus
Cuplikan kode berikut adalah contoh pendaftaran statis untuk penerima siaran yang mendengarkan maksud siaran khusus bersama "ACTION_SHOW_TOAST
" dalam nama aksinya:
name
penerima adalah nama modul ditambah nama subkelasBroadcastReceiver
yang didefinisikan di atas (AlarmReceiver
).- Penerima tidak diekspor, berarti tidak ada aplikasi lain yang bisa mengirim siaran ke aplikasi ini.
- Penerima menyertakan filter maksud yang memeriksa apakah maksud yang masuk menyertakan aksi bernama
ACTION_SHOW_TOAST
.<receiver android:name="com.example.myproject.AlarmReceiver" android:exported="false"> <intent-filter> <action android:name="com.example.myproject.intent.action.ACTION_SHOW_TOAST"/> </intent-filter> </receiver>
Filter maksud
Bila sistem menerima maksud implisit untuk memulai aktivitas, sistem akan menelusuri aktivitas terbaik bagi maksud tersebut dengan membandingkannya dengan filter maksud, berdasarkan tiga aspek:
- Aksi: Apakah aksi yang ditetapkan dalam maksud cocok dengan salah satu nama
<action>
yang tercantum dalam filter? Dalam contoh di atas, hanya maksud yang berisiACTION_SHOW_TOAST
dalam nama aksinya yang akan cocok dengan filter tersebut. - Data: Apakah data dalam maksud cocok dengan salah satu tipe
<data>
yang tercantum dalam filter? - Kategori: Apakah setiap kategori dalam maksud cocok dengan
<category>
yang namanya disebutkan dalam filter?
Contoh: Filter maksud untuk maksud siaran sistem
Contoh ini menampilkan filter maksud bagi penerima yang mendengarkan perangkat untuk menyelesaikan booting:
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
Untuk mengetahui selengkapnya tentang menggunakan filter maksud guna memilih maksud, lihat bagian Resolusi Maksud pada panduan maksud.
Jika tidak ada filter maksud yang ditetapkan, penerima siaran hanya bisa diaktifkan dengan maksud siaran eksplisit yang memberi nama komponen berdasarkan nama. (Tindakan ini mirip dengan cara Anda meluncurkan aktivitas melalui nama kelasnya bersama maksud eksplisit.)
Jika Anda menggunakan pendaftaran statis untuk penerima siaran, sistem Android akan membuat proses baru untuk menjalankan penerima siaran jika tidak ada proses berjalan yang dikaitkan dengan aplikasi Anda. Ini berarti penerima akan merespons, sekalipun aplikasi Anda tidak berjalan.
Pendaftaran dan menghapus pendaftaran dinamis
Anda juga bisa mendaftarkan penerima siaran secara dinamis, yang mengikat operasinya ke daur hidup aktivitas. Untuk mendaftarkan penerima Anda secara dinamis, panggil registerReceiver()
dan teruskan objek BroadcastReceiver
dan filter maksud. Misalnya:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_SHOW_TOAST);
mReceiver = new AlarmReceiver();
registerReceiver(mReceiver, intentFilter);
Anda juga perlu mencabut pendaftaran penerima dengan memanggil unregisterReceiver()
dan meneruskan objek BroadcastReceiver
. Misalnya:
unregisterReceiver(mReceiver);
Tempat Anda memanggil metode ini bergantung pada daur hidup yang diinginkan objek BroadcastReceiver
:
- Jika penerima hanya diperlukan bila aktivitas terlihat (misalnya, untuk menonaktifkan fungsi jaringan bila jaringan tidak tersedia), maka daftarkan penerima di
onResume()
. Hapus pendaftaran penerima dionPause()
. - Anda juga bisa menggunakan pasangan metode
onStart()
/onStop()
atauonCreate()/onDestoy()
, jika pasangan tersebut lebih tepat untuk kasus penggunaan Anda.
Panduan keamanan
Bila Anda menggunakan maksud siaran dan penerima siaran, informasi akan dikirim di antara aplikasi, yang akan menimbulkan risiko keamanan. Untuk menghindari risiko ini, Anda bisa menggunakan LocalBroadcastManager
(dijelaskan di bawah ini), atau Anda bisa mengikuti panduan ini:
- Pastikan nama tindakan maksud dan string lainnya ada dalam namespace yang Anda miliki, jika tidak maka Anda akan mengalami konflik dengan aplikasi lain secara tidak sengaja. Namespace maksud bersifat global.
- Bila Anda menggunakan
registerReceiver()
, aplikasi apa pun bisa mengirim siaran ke penerima yang didaftarkan itu. Untuk mengontrol siapa yang bisa mengirimkan siaran, gunakan izin yang dijelaskan di bawah ini. - Bila Anda mendaftarkan penerima siaran secara statis, aplikasi lainnya bisa mengirim siaran ke penerima tersebut, filter apa pun yang Anda tetapkan. Untuk mencegah aplikasi lain mengirim ke penerima tersebut, jadikan aplikasi itu tidak tersedia dengan
android:exported="false"
. - Bila Anda menggunakan
sendBroadcast()
atau metode terkait, aplikasi lain akan bisa menerima siaran Anda. Untuk mengontrol siapa saja yang bisa menerima siaran tersebut, gunakan izin yang dijelaskan di bawah ini.
Baik pengirim maupun penerima siaran bisa memberlakukan izin akses:
Untuk memberlakukan izin saat mengirim siaran, berikan argumen izin bukan-nol ke
sendBroadcast()
.Hanya penerima yang telah diberi izin ini (dengan memintanya melalui tag
<uses-permission>
di AndroidManifest.xml) yang akan bisa menerima siaran.Untuk memberlakukan izin saat menerima siaran, berikan izin bukan-nol saat mendaftarkan penerima Anda, baik saat memanggil
registerReceiver()
maupun dalam tag statis<receiver>
di AndroidManifest.xml.Hanya penyiar yang telah diberi izin ini (dengan memintanya melalui tag
<uses-permission>
di AndroidManifest.xml) yang akan bisa mengirimkan maksud ke penerima. Penerima harus meminta izin di manifes, terlepas apakah pengirim didaftarkan secara statis atau dinamis.
[LocalBroadcastManager]
Agar tidak perlu menangani aspek keamanan yang dijelaskan dalam Panduan keamanan, gunakan kelas LocalBroadcastManager
. LocalBroadcastManager
memungkinkan Anda mengirim dan menerima siaran dalam satu proses dan satu aplikasi, sehingga Anda tidak perlu khawatir tentang keamanan lintas aplikasi.
Mengirim siaran lokal
Untuk mengirim siaran menggunakan LocalBroadcastManager
:
- Dapatkan instance
LocalBroadcastManager
dengan memanggilgetInstance()
dan meneruskan konteks aplikasi. - Panggil
sendBroadcast()
di instance, dengan meneruskan maksud yang ingin disiarkan.
Misalnya:
LocalBroadcastManager.getInstance(this).sendBroadcast(customBroadcastIntent);
Mendaftarkan penerima Anda untuk siaran lokal
Untuk mendaftarkan penerima Anda guna menerima siaran lokal saja:
- Dapatkan instance
LocalBroadcastManager
dengan memanggilgetInstance()
dan meneruskan konteks aplikasi. - Panggil
registerReceiver()
, dengan meneruskan penerima dan filter maksud seperti yang diinginkan untuk penerima siaran biasa. Anda harus mendaftarkan penerima lokal secara dinamis, karena pendaftaran statis di manifes tidak tersedia.
Misalnya:
LocalBroadcastManager.getInstance(this).registerReceiver
(mReceiver, new IntentFilter(CustomReceiver.ACTION_CUSTOM_BROADCAST));
Untuk mencabut pendaftaran penerima siaran:
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
Praktik terkait
Latihan terkait dan dokumentasi praktik ada di Dasar-Dasar Developer Android: Praktik.